package cola.rh.System.Service.impl;


import cola.rh.System.Entity.Menu;
import cola.rh.System.Entity.RoleMenu;
import cola.rh.System.Entity.vo.AssginMenuVo;
import cola.rh.System.Entity.vo.MetaVo;
import cola.rh.System.Entity.vo.RouterVo;
import cola.rh.System.Mapper.MenuMapper;
import cola.rh.System.Mapper.RoleMenuMapper;
import cola.rh.System.Service.MenuService;
import cola.rh.System.common.result.PublicCodeEnum;
import cola.rh.System.common.utils.MenuHelper;
import cola.rh.System.exception.ColaException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Name: MenuServiceImpl
 * @Author: Cola
 * @Time: 2023/3/11 14:01
 * @Description: MenuServiceImpl
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Override
    public List<Menu> findNodes() {
        /*全部权限列表*/
        List<Menu> MenuList = this.list();
        if (CollectionUtils.isEmpty(MenuList)) return null;

        /*构建树形数据*/
        List<Menu> result = MenuHelper.buildTree(MenuList);
        return result;
    }


    @Override
    public boolean removeMenuById(Serializable id) {
        int count = this.count(new LambdaQueryWrapper<Menu>().eq(Menu::getParentId, id));
        if (count > 0) {
            throw new ColaException(201, "菜单不能删除");
        }
        menuMapper.deleteById(id);
        return false;
    }

    @Override
    public List<Menu> findMenuByRoleId(Long roleId) {
        /* 查询所有 Menu 列表 */
        List<Menu> allMenuList = this.list(new LambdaQueryWrapper<Menu>().eq(Menu::getStatus, 1));

        /* 查询该 roleId 对应的 RoleMenu 列表 */
        List<RoleMenu> existRoleMenuList = roleMenuMapper.selectList(
                new LambdaQueryWrapper<RoleMenu>().
                        eq(RoleMenu::getRoleId, roleId));
        /* 该 roleId 具有的 menuId 列表 */
        List<Long> menuIdList = existRoleMenuList.stream().map(
                roleMenu -> roleMenu.getMenuId()
        ).collect(Collectors.toList());


        allMenuList.forEach(menu -> {
            if (menuIdList.contains(menu.getId())) {
                menu.setSelect(true);
            } else {
                menu.setSelect(false);
            }
        });

        List<Menu> MenuList = MenuHelper.buildTree(allMenuList);
        return MenuList;
    }

    @Transactional
    @Override
    public void doAssign(AssginMenuVo assginMenuVo) {
        /* 先删除 roleId 下所有的 RoleMenu */
        roleMenuMapper.delete(
                new LambdaQueryWrapper<RoleMenu>().
                        eq(RoleMenu::getRoleId, assginMenuVo.getRoleId()));

        /*遍历前端传过来的 menuIdList 如果存在 menuId 就插入*/
        for (Long menuId : assginMenuVo.getMenuIdList()) {
            if (StringUtils.isEmpty(menuId)) continue;
            RoleMenu rolePermission = new RoleMenu();
            rolePermission.setRoleId(assginMenuVo.getRoleId());
            rolePermission.setMenuId(menuId);
            roleMenuMapper.insert(rolePermission);
        }
    }

    @Override
    public List<RouterVo> findUserMenuList(Long userId) {
        List<Menu> menuList = null;
        /*判断是否为管理员*/
        if (userId.longValue() == PublicCodeEnum.ADMIN_CODE.getCode()) {
            /*查询所有菜单列表*/
            menuList = this.list(new LambdaQueryWrapper<Menu>().
                    eq(Menu::getStatus, PublicCodeEnum.STATUS_OK.getCode()).
                    orderByAsc(Menu::getSortValue));
        } else {
            menuList = menuMapper.findListByUserId(userId);
        }
        /*构建路由结构*/
        List<Menu> menuTreeList = MenuHelper.buildTree(menuList);
        List<RouterVo> routerVoList = this.buildMenus(menuTreeList);
        return routerVoList;
    }

    /**
     * 根据菜单构建路由
     *
     * @param menus menus
     * @return
     */
    private List<RouterVo> buildMenus(List<Menu> menus) {
        List<RouterVo> routers = new LinkedList<>();
        for (Menu menu : menus) {
            RouterVo router = new RouterVo();
            router.setHidden(false);
            router.setAlwaysShow(false);
            router.setPath(getRouterPath(menu));
            router.setComponent(menu.getComponent());
            router.setMeta(new MetaVo(menu.getName(), menu.getIcon()));
            List<Menu> children = menu.getChildren();
            /*加载列表*/
            if (menu.getType().intValue() == PublicCodeEnum.MENU_CODE.getCode()) {
                /*加载隐藏路由*/
                List<Menu> hiddenMenuList = children.stream().
                        filter(item -> !StringUtils.isEmpty(item.getComponent()))
                        .collect(Collectors.toList());
                for (Menu hiddenMenu : hiddenMenuList) {
                    RouterVo hiddenRouter = new RouterVo();
                    /*Hidden 为 true 表示为隐藏路由*/
                    hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    hiddenRouter.setMeta(new MetaVo(hiddenMenu.getName(), hiddenMenu.getIcon()));
                    /*添加到路由*/
                    routers.add(hiddenRouter);
                }
            } else {
                if (!CollectionUtils.isEmpty(children)) {
                    if (children.size() > 0) {
                        router.setAlwaysShow(true);
                    }
                    router.setChildren(buildMenus(children));
                }
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(Menu menu) {
        String routerPath = "/" + menu.getPath();
        if (menu.getParentId().intValue() != PublicCodeEnum.PARENT_CODE.getCode()) {
            routerPath = menu.getPath();
        }
        return routerPath;
    }

    @Override
    public List<String> findUserPermsList(Long userId) {
        /*判断是否为超级管理员*/
        List<Menu> menuList = null;
        if (userId.longValue() == PublicCodeEnum.ADMIN_CODE.getCode()) {
            menuList = this.list(new LambdaQueryWrapper<Menu>().eq(Menu::getStatus, PublicCodeEnum.STATUS_OK.getCode()));
        } else {
            menuList = menuMapper.findListByUserId(userId);
        }
        List<String> permsList = menuList.stream().
                filter(item -> item.getType() == PublicCodeEnum.BUTTON_CODE.getCode()).
                map(item -> item.getPerms()).
                collect(Collectors.toList());
        return permsList;
    }

}
